// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace System.Threading.Actors.Utilities
{
    public static class NetworkConfiguration
    {
        // On machines with both IPv4 and IPv6 network stacks, should we use IPv6 or IPv4?
        public static readonly bool PreferIPv6 = false;

        public static IPAddress GetIPAddress(AddressFamily addressFamily)
        {
            IPHostEntry entry = Dns.GetHostEntry(string.Empty);
            foreach (IPAddress addr in entry.AddressList)
            {
                if (addr.AddressFamily == addressFamily &&
                    !IPAddress.IsLoopback(addr))
                {
                    return addr;
                }
            }

            throw new WebException("FAILED to grab IPAddress for self");
        }

        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "AddressOr")]
        public static string GetIPAddressOrHostName()
        {
            return GetIPAddressOrHostName(false, PreferIPv6);
        }

        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "AddressOr")]
        public static string GetIPAddressOrHostName(bool isFabricReplicatorAddress, bool preferIPv6)
        {
            IPHostEntry entry = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipv4Address = entry.AddressList.FirstOrDefault<IPAddress>(
                ipAddress => (ipAddress.AddressFamily == AddressFamily.InterNetwork) && !IPAddress.IsLoopback(ipAddress));

            if (!preferIPv6 && ipv4Address != null)
            {
                return ipv4Address.ToString();
            }

            IPAddress ipv6Address = entry.AddressList.FirstOrDefault<IPAddress>(
                ipAddress => (ipAddress.AddressFamily == AddressFamily.InterNetworkV6) && !IPAddress.IsLoopback(ipAddress));

            if (ipv6Address != null)
            {
                if (isFabricReplicatorAddress)
                {
                    return "[" + ipv6Address.ToString() + "]";
                }
                else
                {
                    return ipv6Address.ToString();
                }
            }
            else
            {
                if (ipv4Address != null)
                    return ipv4Address.ToString();

                return entry.HostName;
            }
        }
    }
}
